using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform;
using Avalonia.Platform.Storage;
using LuckyCoding.FileView;
using LuckyCoding.Models;
using LuckyCoding.ViewModels;
using Newtonsoft.Json;

namespace LuckyCoding.Views;

public partial class MainWindow : Window
{
    private List<string> Contexts { get; } = new();
    private List<int> Map { get; set; } = new();
    private int Index { get; set; }

    public MainWindow()
    {
        InitializeComponent();
    }

    private async void OpenSettingClick(object? sender, RoutedEventArgs e)
    {
        var window = new DispositionView();
        var result = await window.ShowDialog<DispositionModel>(this);
        //if(DataContext is not MainWindowViewModel model || result == null)return;
        //model.Disposition = result;
    }

    private async void OpenClick(object? sender, RoutedEventArgs e)
    {
        var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions() { AllowMultiple = false });
        var file = result.FirstOrDefault();
        if (file == null) return;
        await using var context = await file.OpenReadAsync();
        
        using var stream = new StreamReader(context);
        var s = await stream.ReadToEndAsync();

        ContextChange(s, file.Path.LocalPath, "code");
    }

    private void ContextChange(string s, string path, string type)
    {
        if (DataContext is not MainWindowViewModel model) return;
        if (model.Files.Any(x => x.Location == path)) return;

        if (Control.Content is EditFileView view)
        {
            Contexts[Index] = view.Editor.Text;
        }

        if (type == "code")
        {
            model.Files.Add(new CodeFileModel(path));
            Control.Content = new EditFileView(path, s);
            Contexts.Add(s);
            Index = model.Files.Count - 1;
            return;
        }

        if (type == "web")
        {
            model.Files.Add(new WebFileModel(path));
            Control.Content = new WebFileView(path);
            Index = model.Files.Count - 1;
            return;
        }

        if (type == "setting")
        {
            model.Files.Add(new SettingFileModel());
            Control.Content = new SettingView();
            Index = model.Files.Count - 1;
        }
    }

    private async void RunClick(object? sender, RoutedEventArgs e)
    {
        if (Control.Content is not EditFileView edit)return;
        var url = new Uri($"avares://LuckyCoding/Assets/RunScript/{Path.GetExtension(edit.FilePath)[1..]}.json");
        await using var stream = AssetLoader.Open(url);
        using var reader = new StreamReader(stream);
        var s = await reader.ReadToEndAsync();
        var result = JsonConvert.DeserializeObject<DispositionModel>(s);
        var order = result?.BuildOrder(new Dictionary<string, string>()
        {
            { "%f", edit.FilePath }
        });

        await TerminalView.Run(order);

    }

    private void EditChanged(object? sender, SelectionChangedEventArgs e)
    {
        if (ViewList.SelectedIndex < 0) return;
        if (Control.Content is EditFileView view)
        {
            Contexts[Index] = view.Editor.Text;
            if (DataContext is not MainWindowViewModel model) return;
            view.Change(Contexts[ViewList.SelectedIndex], model.Files[Index].Location!);
            Index = ViewList.SelectedIndex;
        }
    }

    private async void FolderOpen(object? sender, RoutedEventArgs e)
    {
        // FolderTree
        var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { AllowMultiple = false });
        var folder = result.FirstOrDefault();
        if (folder == null) return;
        FolderTree.ItemsSource = new[] { new FolderModel(folder.Path.LocalPath) };
    }

    private void FolderChanged(object? sender, SelectionChangedEventArgs e)
    {
        var a = (FolderModel)FolderTree.SelectedItem!;
        if (a == null) return;
        if (a.Children.Count == 0 && !string.IsNullOrEmpty(a.Location))
            ContextChange(File.ReadAllText(a.Location), a.Location, "code");
    }

    private void SaveClick(object? sender, RoutedEventArgs e)
    {
        if (ViewList.SelectedIndex < 0)
        {
            SaveAtClick(sender,e);
        }
        else
        {
            if (Control.Content is not EditFileView edit)return;
            if(DataContext is not MainWindowViewModel model)return;
            File.WriteAllText(model.Files[Index].Location!,edit.Editor.Text);
            Contexts[Index] = edit.Editor.Text;
            edit.Change(Contexts[ViewList.SelectedIndex], model.Files[Index].Location!);
        }
    }

    private void SaveAllClick(object? sender, RoutedEventArgs e)
    {
        if (ViewList.SelectedIndex < 0)return;
        if(DataContext is not MainWindowViewModel model)return;
        for (int i = 0; i < Contexts.Count; i++)
            File.WriteAllText(model.Files[i].Location!,Contexts[i]);
        if (Control.Content is not EditFileView edit)return;
        Contexts[Index] = edit.Editor.Text;
        edit.Change(Contexts[ViewList.SelectedIndex], model.Files[Index].Location!);
    }

    private async void SaveAtClick(object? sender, RoutedEventArgs e)
    {
        if (Control.Content is not EditFileView edit)return;
        var file = await StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions() { });
        if(file == null)return;
        var s = await file.OpenWriteAsync();
        var writer = new StreamWriter(s);
        await writer.WriteAsync(edit.Editor.Text);
        await writer.DisposeAsync();
        await s.DisposeAsync();
    }
}